package org.example.company.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.example.common.Constant;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.*;

@Component
public final class JwtTokenUtils {
    private static Key getInstance(String salt){
        SignatureAlgorithm algorithm = SignatureAlgorithm.HS256;
        //将字节数组编码为 Base64 字符串
        String apKey = DatatypeConverter.printBase64Binary(salt.getBytes());
        //前生成的 Base64 字符串 apKey 解析回字节数组。
        //这个步骤通常是为了保证生成的字节数组符合特定格式或长度，以便生成密钥。
        byte[] apiSecretBytes = DatatypeConverter.parseBase64Binary(apKey);
        SecretKeySpec secretKeySpec = new SecretKeySpec(apiSecretBytes,algorithm.getJcaName());
        return secretKeySpec;
    }
    //生成一个token
    public static String createWebTokenJwtAuth(Map<String,Object> claims,String salt,Integer exp){
        String token = Jwts.builder()
                .setClaims(claims)
                .setExpiration(DateUtils.addSeconds(new Date(),exp))
                .signWith(SignatureAlgorithm.HS256, getInstance(salt)).compact();
        return token;
    }

    public static Map<String,Object> verifyJwtWebToken(String token,String salt){
        Map<String, Object> jwtClaims= Jwts.parser().setSigningKey(getInstance(salt)).parseClaimsJws(token).getBody();
        return jwtClaims;
    }

    //验证传入的 token，并返回一个 Authentication 对象，用于 Spring Security 中的身份验证。
    public static Authentication getAuthentication(String token, String salt){
        HashMap<String, Object> map = new HashMap<>();
        //调用 verifyJwtWebToken 方法来验证传入的 token，并且使用 salt 作为密钥。
        //verifyJwtWebToken 返回一个 Map，其中包含解析后的 JWT 内容。
        Map<String, Object> StringObjectMap = verifyJwtWebToken(token, salt);
        //验证返回的 StringObjectMap 是否为空，或者其中的 user-info 字段是否为空。
        //如果 user-info 为空，则返回 null，表示身份验证失败。
        if(StringObjectMap==null||StringObjectMap.get(Constant.TOKEN_USER_INFO)==null){
            return null;
        }
        LinkedHashMap<String,Object> userDetails =(LinkedHashMap) StringObjectMap.get(Constant.TOKEN_USER_INFO);
        //根据用户的详细信息（userDetails）来生成权限列表。
        //如果 userDetails 为空，使用 AuthorityUtils.NO_AUTHORITIES，表示没有任何权限。
        //如果有 userDetails，使用 AuthorityUtils.commaSeparatedStringToAuthorityList 方法将 user-info 中的 "role" 字段解析为权限列表。
        List<GrantedAuthority> authorities = null == userDetails ? AuthorityUtils.NO_AUTHORITIES : AuthorityUtils.commaSeparatedStringToAuthorityList(String.valueOf(userDetails.get("role")));
        //创建一个 User 对象作为身份验证的主体 (principal)。
        //使用 userDetails 中的 "username" 作为用户名。
        //密码字段为空字符串（因为这里的密码在 JWT 验证时已经不需要了）。
        //传入的 authorities 列表用于指示该用户的权限。
        User principal = new User((String) userDetails.get(Constant.TOKEN_USER_INFO_USERNAME), "", authorities);
        //principal：表示认证主体（用户）。
        //token：作为凭证，表明这是通过 JWT 验证的。
        //authorities：用户的权限列表。
        return new UsernamePasswordAuthenticationToken(principal,token,authorities);
    }}
